<?php
/**
 * Created by PhpStorm.
 * User: Larry
 * Date: 16/4/5
 * Time: 19:15
 */

namespace App\Services\Wechat;


use App\Models\Cart;
use App\Models\Goods;
use App\Models\Member;
use App\Models\MemberLottery;
use App\Models\MemberPayinLog;
use App\Models\MemberPayLog;
use App\Models\Period;
use App\Models\Yuncode;
use App\Models\PeriodsResult;
use App\Models\Order;
use App\Models\Buy as Modelbuy;
use App\Services\Notice\TemplateNotice;

use DB;
use Request;

class Pay
{
    public function __construct(
        Period $period,
        Qishu $qishu,
        MemberPayLog $memberPayLog,
        Cart $cart,
        Goods $goods,
        Buy $buy,
        Yuncode $yuncode,
        Member $member,
        PeriodsResult $periodsResult,
        MemberLottery $lottery,
        Modelbuy $modelbuy,
        MemberPayinLog $payinLog,
        Order $order,
        TemplateNotice $templateNotice
    )
    {
        $this->period = $period;
        $this->qishu = $qishu;
        $this->memberPayLog = $memberPayLog;
        $this->cart = $cart;
        $this->goods = $goods;
        $this->buy = $buy;
        $this->yuncode = $yuncode;
        $this->member = $member;
        $this->periodsResult = $periodsResult;
        $this->memberlottery = $lottery;
        $this->modelbuy = $modelbuy;
        $this->payinLog = $payinLog;
        $this->order = $order;
        $this->templateNotice = $templateNotice;
    }

    public function runpay($carts = [], $uid, $sn, $payby = 2)
    {
        $period = $this->period->getPeriod($carts['goods_id']);
        //检查数据是否合格
        $res = $this->checkData($period, $carts, $payby, $sn);
        if (!$res['status']) {
            return $res;
        }
        //执行购买
        $res = $this->buy($sn, $uid, $period, $carts, $payby);
        //限购商品处理
        if($res['status'])
        {
            $goods = $this->goods->getGoods($carts['goods_id']);
            if($goods['xiangoujiage'] >= 1)
            {
                $key = $carts['goods_id'].'_'.$carts['qishu'];
                $data['uid'.$uid] = $uid;
                $this->modelbuy->limitMc($key, $data);
            }
            //清空购物车
            $this->clearCart($uid, $carts['goods_id']);
        }
        return $res;


    }

    /**
     * 订单号
     */
    function generateOrderNo()
    {
        list($tmp1, $tmp2) = explode(' ', microtime());
        $msec = (float)sprintf('%.0f', (floatval($tmp1) + floatval($tmp2)) * 1000);
        return $msec;
    }

    private function checkData($period, $carts, $payby, $sn)
    {
        $res['status'] = 1;
        //1.当前商品的期数判断 (读 cache)
        if ($period['qishu'] != $carts['qishu']) //TODO: 考虑是否读 goods 源表 期数做比对
        {
            $res['status'] = 0;
            $res['message'] = "{$period['title']}已经过期!";
        }
        if ($period['shenyurenshu'] < $carts['money']) {
            $res['status'] = 0;
            $res['message'] = "{$period['title']}剩余次数不足";
        }
        //将微信支付进行充值
        if (!$res['status'] && $payby == 2) {
            //写入充值记录
            $data['uid'] = $carts['uid'];
            $data['out_trade_no'] = $sn;
            $data['money'] = $carts['money'];
            $data['payby'] = 2;
            $data['remark'] = "购买失败进行充值";
            $this->payinLog->add($data);
            //更新用户余额
            $this->member->money($carts['uid'], $carts['money']);
        }
        return $res;
    }

    private function buy($sn, $uid, $period, $carts, $payby)
    {
        DB::beginTransaction();
        try {
            if ($payby == 1) {
                //扣除用户余额
                $money = $carts['money'];
                $this->member->decMoney($uid, $money);
            }
//            dd(1);
            //插入购买记录
            $a = $this->addBuyLog($carts, $uid, $sn);
//            dd($a);
            //更新期数
            $b = $this->updatePeriod($period, $carts, $payby);
//            dd($b);
            //插入支付日志
            $c = $this->addPayLog($period, $sn, $uid, $carts, $payby);
            DB::commit();
            $res['status'] = 1;
            $res['message'] = "成功~!";
        } catch (\Exception $e) {
            DB::rollBack();
            $res['status'] = 0;
            $res['message'] = "数据异常支付失败~!";
        }
        return $res;
    }

    private function addBuyLog($carts, $uid, $sn)
    {
        //获取云购码
        $yuncode = $this->qishu->generateYungouCode($carts['goods_id'], $carts['money']);
//        dd($yuncode);
        if (!$yuncode) {
            return false;
        }
        //写入购买记录及随机云购码
        $res = $this->buy->add($carts, $uid, $yuncode, $sn);
        if (!$res) {
            return false;
        }
        return true;
    }

    public function addPayLog($period, $sn, $uid, $carts, $payby)
    {
        $data['gid'] = $carts['goods_id'];
        $data['uid'] = $uid;
        if (strlen($sn) >= 32) {
            $data['out_trade_no'] = $sn;
        } else {
            $data['sn'] = $sn;
        }
        $data['qishu'] = $carts['qishu'];
        $data['payby'] = $payby;
        $data['money'] = $carts['money'];
        $data['remark'] = $period['title'];
        //写入支付日志
        $res = $this->memberPayLog->add($data);
        if (!$res) {
            return false;
        }
        return true;
    }

    //清除购物车
    public function clearCart($uid, $goodsId)
    {
        $this->cart->delCacheCart($uid, $goodsId);
        $res = $this->cart->del(['uid' => $uid]);
        if (!$res) {
            return false;
        }
        return true;
    }

    /**
     * 更新期数数据
     */
    public function updatePeriod($period, $carts, $payby)
    {

        //更新期数表
        $where['goods_id'] = $period['goods_id'];
        $where['qishu'] = $period['qishu'];
        $data['canyurenshu'] = $period['canyurenshu'] + $carts['money'];
        $data['shenyurenshu'] = $period['shenyurenshu'] - $carts['money'];
        $res = $this->period->up($where, $data);
        if (!$res) {
            return false;
        }
        $this->period->delGoodsPeriodMc($period['goods_id'], $period['qishu']);//清除商品期数缓存
        //开奖和生成新的一期
        if ($period['shenyurenshu'] - $carts['money'] <= 0) {
            $result = $this->periodsResult->add($period['goods_id'], $period['qishu'], $period['zongrenshu']);
//            dd($result);
            if (!is_array($result)) {
                return false;
            }
            $newData['m_uid'] = $result['code_result']['uid'];
            $newData['q_user_ip'] = Request::ip();
            $newData['q_user_money'] = $carts['money'];
            $newData['q_user_code'] = $result['code'];
            $newData['q_counttime'] = $result['sum'];
            $newData['q_end_time'] = $this->microtime_float();
            $res1 = $this->period->up($where, $newData);//更新期数获奖信息
            $this->sendLotteryMessage($newData['q_end_time'],$result['code'],$period['qishu'],$result['code_result']['uid'],$period['title']);
//            dd($res1);
            if (!$res1) {
                return false;
            }
            $res5 = $this->lottery($result, $period);//插入中奖记录表
            if (!$res5) {
                return false;
            }

            $goods = $this->goods->getGoods($carts['goods_id']);

            $orderData['sn'] = $this->generateOrderSn();
            $orderData['goods_id'] = $period['goods_id'];
            $orderData['qishu'] = $period['qishu'];
            $orderData['zongrenshu'] = $period['zongrenshu'];
            $orderData['money'] = $period['money'];
            $orderData['code'] = $result['code'];
            $orderData['uid'] = $result['code_result']['uid'];
            $orderData['type'] = $goods->virtual;
            $orderData['pay_type'] = $payby;
            $orderData['comeouttime'] = $newData['q_end_time'];
            $orderData['lottery_id'] = $res5['lottery_id'];
            $res6 = $this->order->add($orderData);
            if (!$res6) {
                return false;
            }
            if ($period['qishu'] < $goods['maxqishu']) {
                $res2 = $this->period->add($goods);//开新一期
                if (!$res2) {
                    return false;
                }
                $res3 = $this->yuncode->generateCode($goods->id, $goods->zongrenshu); //生成新期数码表
                if (!$res3['status']) {
                    return false;
                }
                $goodData['qishu'] = $goods->qishu + 1;
            } else {
                $goodData['status'] = 2;
            }
            $res4 = $this->goods->up(['id' => $goods->id], $goodData); //更新商品信息
            if (!$res4) {
                return false;
            }
            $this->goods->delGoodsMc($goods->id); //清除商品MC
            $this->period->delPeriodMc($goods->id); //清除期数MC
            $key = $carts['goods_id'].'_'.$carts['qishu'];
            $this->modelbuy->delLimitMc($key);
        } else {
            //更新期数MC
            $this->period->incrementRenci($period['goods_id'], $carts['money']);
        }
        return true;
    }

    function microtime_float()
    {
        return date("Y-m-d H:i:s") . '.' . substr(explode(".", microtime())[1], 0, 3);//输出格式 2016-03-2922:55:42.822
    }

    /**
     * 插入中奖记录表和发送消息
     */
    public function lottery($result, $period)
    {
        $data['uid'] = $result['code_result']['uid'];
        $data['goods_id'] = $period['goods_id'];
        $data['periods_id'] = $period['qishu'];
        $where = $data;
        $money = $this->modelbuy->getSum($where, 'money');

        $data['summoney'] = $period['zongrenshu'];
        $data['money'] = $money;
        $data['comeouttime'] = $this->microtime_float();
        $data['type'] = 0;
        $data['status'] = 0;
        $data['shartstatus'] = 0;
        $res = $this->memberlottery->add($data);
        if (!$res) {
            return false;
        }
        $backData['lottery_id'] = $res;
        $backData['comeouttime'] = $data['comeouttime'];
        //TODO::发送消息和生成订单
        return $backData;
    }

    //生成中奖订单号
    function generateOrderSn()
    {
        return 'X' . time() . substr(microtime(), 2, 6) . rand(0, 9);
    }

    public function sendLotteryMessage($comeouttime,$code,$qishu,$uid,$goodsName)
    {
        $member = $this->member->getMember($uid);
        $url = action('Wechat\MemberController@getXingyun');
        $first = '恭喜您,在夺宝中胜出';
        $huodong = '中奖号码 '.$code;
        $remark = '揭晓时间: '.date('Y-m-d H:i:s',strtotime($comeouttime))." \n请在幸运记录中领取,祝你生活愉快!\n欢迎再次购买!";
        $goodsName = '[ '.$qishu.' ] '.$goodsName;
        $res = $this->templateNotice->sendLotteryMassage($member['openid'], $url,$first,$huodong,$goodsName,$remark);
        return $res;
    }

}